#include <tasks_manager/data_compatible.h>

DataCompatible::DataCompatible(){
    __task_db = "/home/aoting/user_config/task_db/task.db";
    __task_record_db = "/home/aoting/user_config/task_db/record.db";
    __elevator_timertask_db = "/home/aoting/user_config/elevator/elevator_timertask.db";

    // 检验文件路径，并返回指针
    auto CheckFileExist = [&](string file_path) -> boost::shared_ptr<SqliteBridge> {
        if(file_manager::IsExists(file_path))
            return boost::make_shared<SqliteBridge>(file_path);
        return nullptr;
    };   

    __task_db_ptr = CheckFileExist(__task_db); 
    __task_record_ptr = CheckFileExist(__task_record_db);
    __elevator_timertask_ptr = CheckFileExist(__elevator_timertask_db);

    // TEST
    // AllTaskData();    
    // AllTimerTaskData();
    // AllElevatorTimerTaskData();
}


DataCompatible::~DataCompatible(){
    
}

// 消息转换 std::string -> Json::Value
Json::Value DataCompatible::String2JsonValue(string str_data){
    Json::Reader reader;
    Json::Value json_data;
    reader.parse(str_data, json_data); 
    return json_data;
}


// 获取所有任务数据
vector<TaskSingle> DataCompatible::AllTaskData(){
    cout << "AllTaskData......" << endl;
    vector<TaskSingle> task_list;
    if(!__task_db_ptr)
        return task_list;
    // 获取所有任务数据
    string sql_cmd = "SELECT * FROM task_manager";
    Json::Value json_data = __task_db_ptr->Sqlite3Exec(sql_cmd);
    // for(auto& task_item : json_data)
    for(int i=0; i< json_data.size(); i++){
        Json::Value task_item = json_data[i];
        // 获取任务数据
        TaskBase task_base;
        // 任务名称
        if(file_manager::CheckItemIsValid(task_item, "task_name"))
            task_base.task_name = task_item["task_name"].asString();
        // 任务ID
        if(file_manager::CheckItemIsValid(task_item, "id"))
            task_base.task_id = task_item["id"].asString();
        // 地图名称
        if(file_manager::CheckItemIsValid(task_item, "map_name")){
            task_base.map_base.name = task_item["map_name"].asString();
        }
        // 任务执行方式和路径是否动态调整
        // 0-TEMP 立即执行，不存储   （已删除此操作）
        // 1-TIMER 立即执行，存储    （已删除此操作）
        // 2-STATIC 不立即执行，存储，路径静态
        // 3-DYNAMIC 不立即执行，存储，路径动态
        if(file_manager::CheckItemIsValid(task_item, "type")){
            task_base.dynamic_adjust_path = task_item["type"].asString() == "3";
        }
        // 任务起点
        if(file_manager::CheckItemIsValid(task_item, "path_start")){
            Json::Value parser_data = String2JsonValue(task_item["path_start"].asString());
            geometry_msgs::Pose pose;
            pose.position.x = parser_data["x"].asFloat();
            pose.position.y = parser_data["y"].asFloat();
            task_base.start = pose;
        }
        // 任务区域轮廓
        if(file_manager::CheckItemIsValid(task_item, "global_area")){
            Json::Value parser_data = String2JsonValue(task_item["global_area"].asString());
            v3_msgs::PolygonData polygon_data;
            for(auto data : parser_data["points"]){
                geometry_msgs::Pose pose;
                pose.position.x = data["x"].asFloat();
                pose.position.y = data["y"].asFloat();
                polygon_data.poses.emplace_back(pose);
            } 
            task_base.polygon = polygon_data;
        }
        // 任务执行速度
        if(file_manager::CheckItemIsValid(task_item, "global_spd")){
            string speed = task_item["global_spd"].asString();
            if(speed == "1"){
                task_base.task_speed = TaskSpeed::LOW_SPEED;
            }
            if(speed == "2"){
                task_base.task_speed = TaskSpeed::MIDDLE_SPEED;
            }
            if(speed == "3"){
                task_base.task_speed = TaskSpeed::HIGH_SPEED;
            }
        }
        // 任务绑定清洁模式
        if(file_manager::CheckItemIsValid(task_item, "clean_mode_name")){
            task_base.utils_mode = task_item["clean_mode_name"].asString();
        }
        // 清扫模式
        // 0-NORM_SWEEP  标准（弓字型）
        // 1-ROUND_SWEEP  标准（回字型）
        // 2-PERIMETER_SWEEP 贴边
        // 3-NROM_PERI  标准（弓字型） + 贴边
        // 4-ROUND_PERI  标准（回字型） + 贴边
        // 5-FOLLOW_TEACH   跟随模式
        // 6-P2P    P2P模式
        // 7-FLOOR_TRANS    楼层转换
        // 16-CHARGE    充电
        // 8-AUTO_PATH  自适应路径
        // 数据库中一般为0、1、2、3、4、5类型，需要兼容
        PathGenerateType path_type = PathGenerateType::UNKNOWN;
        PathGenerateType edge_path_type = PathGenerateType::UNKNOWN;
        if(file_manager::CheckItemIsValid(task_item, "clean_mode")){
            string clean_mode = task_item["clean_mode"].asString();
            if(clean_mode == "0"){
                task_base.control_mode = TaskControlMode::SWEEP_STANDARD_MODE;
                path_type = PathGenerateType::BOUSTROPHEDON_METHOD;
                task_base.task_type  = TaskType::SWEEP_TASK;
                task_base.path_gen.path_types.emplace_back(PathGenerateType::BOUSTROPHEDON_METHOD);
            }
            if(clean_mode == "1"){
                task_base.control_mode = TaskControlMode::SWEEP_STANDARD_MODE;
                path_type = PathGenerateType::WRAPPER_METHOD;
                task_base.task_type  = TaskType::SWEEP_TASK;
                task_base.path_gen.path_types.emplace_back(PathGenerateType::WRAPPER_METHOD);
            }
            if(clean_mode == "2"){
                task_base.control_mode = TaskControlMode::SWEEP_EDGE_MODE;
                edge_path_type = PathGenerateType::MANUAL_METHOD;
                task_base.task_type  = TaskType::TEACH_TASK;
                task_base.path_gen.path_types.emplace_back(PathGenerateType::MANUAL_METHOD);
                task_base.path_gen.path_types_child.emplace_back(PathGenerateType::EDGE_METHOD);
            }
            if(clean_mode == "3"){
                task_base.control_mode = TaskControlMode::SWEEP_STANDARD_AND_EDGE;
                path_type = PathGenerateType::BOUSTROPHEDON_METHOD;
                edge_path_type = PathGenerateType::EDGE_METHOD;
                task_base.task_type  = TaskType::SWEEP_TASK;
                task_base.path_gen.path_types.emplace_back(PathGenerateType::BOUSTROPHEDON_METHOD);
                task_base.path_gen.path_types.emplace_back(PathGenerateType::EDGE_METHOD);
            }
            if(clean_mode == "4"){
                task_base.control_mode = TaskControlMode::SWEEP_STANDARD_AND_EDGE;
                path_type = PathGenerateType::WRAPPER_METHOD;
                edge_path_type = PathGenerateType::EDGE_METHOD;
                task_base.task_type  = TaskType::SWEEP_TASK;
                task_base.path_gen.path_types.emplace_back(PathGenerateType::WRAPPER_METHOD);
                task_base.path_gen.path_types.emplace_back(PathGenerateType::EDGE_METHOD);
            }
            if(clean_mode == "5"){
                task_base.control_mode = TaskControlMode::FOLLOW_MODE;
                path_type = PathGenerateType::MANUAL_METHOD;
                edge_path_type = PathGenerateType::MANUAL_METHOD;
                task_base.task_type  = TaskType::TEACH_TASK;
                task_base.path_gen.path_types.emplace_back(PathGenerateType::MANUAL_METHOD);
                task_base.path_gen.path_types_child.emplace_back(PathGenerateType::EDGE_METHOD);
            }
        }
        // 任务执行路径
        if(file_manager::CheckItemIsValid(task_item, "subtask")){
            Json::Value parser_data = String2JsonValue(task_item["subtask"].asString());
            for(auto subtask : parser_data){
                TaskPath task_path;
                // 子路径清扫模式
                string sweep_mode = subtask["sweep_mode"].asString();
                // 路径数据
                for(auto path_data : subtask["path"]["poses"]){
                    geometry_msgs::Pose pose;
                    pose.position.x = path_data["x"].asFloat();
                    pose.position.y = path_data["y"].asFloat();
                    task_path.poses.emplace_back(pose);
                }
                if(sweep_mode == "0"){
                    task_path.path_type = path_type;
                    task_base.paths.emplace_back(task_path);
                }
                if(sweep_mode == "1"){
                    task_path.path_type = edge_path_type;
                    task_base.edge_paths.emplace_back(task_path);
                }
            }
        }

        // 打印输出
        cout << "[AllTaskData] [" << i << "] " << task_base.task_id 
            << ", task_name: " << task_base.task_name 
            << ", map_name: " << task_base.map_base.name 
            << ", dynamic_adjust_path: " << task_base.dynamic_adjust_path 
            << ", task_speed: " << int(task_base.task_speed) 
            << ", path_type: " << int(path_type) 
            << ", paths size: " << task_base.paths.size() 
            << ", edge_path_type: " << int(edge_path_type) 
            << ", edge_paths size: " << task_base.edge_paths.size() 
            << endl;

        task_base.task_name = task_base.task_name + "_" + task_base.map_base.name;
        TaskSingle task_single;
        task_single.task_base = task_base;
        task_list.emplace_back(task_single);
    }
    return task_list;
}

// 获取所有定时任务数据
vector<TimerTask> DataCompatible::AllTimerTaskData(){
    vector<TimerTask> timer_task_list;

    // 更新所有定时任务数据
    if(!__task_db_ptr)
        return timer_task_list;
    string sql_cmd = "SELECT * FROM timertask_manager";
    Json::Value json_data = __task_db_ptr->Sqlite3Exec(sql_cmd);
    for(int i=0; i< json_data.size(); i++){
        Json::Value timer_task_item = json_data[i];
        // 定时任务数据
        TimerTask timer_task;
        timer_task.multi_maps_shared = false;
        if(file_manager::CheckItemIsValid(timer_task_item, "timertask_name")){
            timer_task.timertask_name = timer_task_item["timertask_name"].asString();
        }
        string map_name = "";
        if(file_manager::CheckItemIsValid(timer_task_item, "map_name")){
            map_name = timer_task_item["map_name"].asString();
        }
        timer_task.map_name = map_name;
        // 存在不同地图下相同定时任务名称
        timer_task.timertask_name = timer_task.timertask_name + "_" + map_name;
        if(file_manager::CheckItemIsValid(timer_task_item, "task_names")){
            // cout << "[AllTimerTaskData] timertask_name: " << timer_task.timertask_name << endl;
            Json::Value parser_data = String2JsonValue(timer_task_item["task_names"].asString());
            for(auto& task : parser_data){
                // task_single
                TaskSingle task_single;
                task_single.task_base.task_name = task.asString() + "_" + map_name;
                task_single.task_base.map_base.name = map_name;
                // task_group
                TaskGroup task_group;
                task_group.group_name = task_single.task_base.task_name;
                task_group.timertask_name = timer_task.timertask_name;
                task_group.task_list.emplace_back(task_single);

                timer_task.taskgroup_list.emplace_back(task_group);
            }
            
        }
        // 时刻表
        vector<string> week_day = {"Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"};
        for(int i=0; i<week_day.size(); i++){
            if(file_manager::CheckItemIsValid(timer_task_item, "task_names")){
                int enable = std::stoi(timer_task_item[week_day[i]].asString());
                timer_task.timetable.emplace_back(enable);
            }
            else{
                timer_task.timetable.emplace_back(0);
            } 
        }
        // 定时任务时间
        if(file_manager::CheckItemIsValid(timer_task_item, "exec_time")){
            timer_task.start_time = timer_task_item["exec_time"].asString();
        }
        // 使能开关
        if(file_manager::CheckItemIsValid(timer_task_item, "enable")){
            timer_task.enable = std::stoi(timer_task_item["enable"].asString()) == 1;
        }

        if(timer_task.taskgroup_list.empty()) continue;
        // 打印输出
        cout << "[AllTimerTaskData] [" << i << "] " 
            << "timertask_name: " << timer_task.timertask_name 
            << ", map_name: " << map_name 
            << ", task_list size: " << timer_task.taskgroup_list[0].task_list.size() 
            << ", enable: " << timer_task.enable 
            << ", start_time: " << timer_task.start_time

            << ", timetable: ";
            for(auto& item : timer_task.timetable){
                cout << item;
            }
            cout << endl;

        timer_task_list.emplace_back(timer_task);
    }

    return timer_task_list;
}


// 获取所有定时任务数据
vector<TimerTask> DataCompatible::AllElevatorTimerTaskData(){
    vector<TimerTask> timer_task_list;

    // 更新所有定时任务数据
    if(!__elevator_timertask_ptr)
        return timer_task_list;
    string sql_cmd = "SELECT * FROM elevator_timertask";
    Json::Value json_data = __elevator_timertask_ptr->Sqlite3Exec(sql_cmd);
    for(int i=0; i< json_data.size(); i++){
        Json::Value timer_task_item = json_data[i];
        // 定时任务数据
        TimerTask timer_task;
        timer_task.multi_maps_shared = true;
        if(file_manager::CheckItemIsValid(timer_task_item, "timertask_name")){
            timer_task.timertask_name = timer_task_item["timertask_name"].asString();
        }
        if(file_manager::CheckItemIsValid(timer_task_item, "task_names") && 
            file_manager::CheckItemIsValid(timer_task_item, "map_names")){
                Json::Value task_parser_data = String2JsonValue(timer_task_item["task_names"].asString());
                Json::Value map_parser_data = String2JsonValue(timer_task_item["map_names"].asString());
                if(task_parser_data.size() == map_parser_data.size()){
                    for(int i=0; i<task_parser_data.size(); i++){
                        // task_single
                        TaskSingle task_single;
                        task_single.task_base.map_base.name = map_parser_data[i].asString();                        
                        task_single.task_base.task_name = task_parser_data[i].asString() + "_" + task_single.task_base.map_base.name;
                        // task_group
                        TaskGroup task_group;
                        task_group.group_name = task_single.task_base.task_name;
                        task_group.timertask_name = timer_task.timertask_name;
                        task_group.task_list.emplace_back(task_single);

                        timer_task.taskgroup_list.emplace_back(task_group);
                    }
                }
        }
        // 时刻表
        vector<string> week_day = {"Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"};
        for(int i=0; i<week_day.size(); i++){
            if(file_manager::CheckItemIsValid(timer_task_item, "task_names")){
                int enable = std::stoi(timer_task_item[week_day[i]].asString());
                timer_task.timetable.emplace_back(enable);
            }
            else{
                timer_task.timetable.emplace_back(0);
            } 
        }
        // 定时任务时间
        if(file_manager::CheckItemIsValid(timer_task_item, "exec_time")){
            timer_task.start_time = timer_task_item["exec_time"].asString();
        }
        // 使能开关
        if(file_manager::CheckItemIsValid(timer_task_item, "enable")){
            timer_task.enable = std::stoi(timer_task_item["enable"].asString()) == 1;
        }
        // 打印输出
        if(timer_task.taskgroup_list.empty()) continue;
        cout << "[AllElevatorTimerTaskData] [" << i << "] " 
            << "timertask_name: " << timer_task.timertask_name 
            << ", task_list size: " << timer_task.taskgroup_list[0].task_list.size() 
            << ", enable: " << timer_task.enable 
            << ", start_time: " << timer_task.start_time

            << ", timetable: ";
            for(auto& item : timer_task.timetable){
                cout << item;
            }
            cout << endl;

        timer_task_list.emplace_back(timer_task);
    }
    return timer_task_list;
}

// 获取所有任务记录数据
vector<TaskRecord> DataCompatible::AllTaskRecordData(){
    vector<TaskRecord> task_record_list;
    if(!__task_record_ptr)
        return task_record_list;
    string sql_cmd = "SELECT * FROM task_record";
    Json::Value json_data = __task_record_ptr->Sqlite3Exec(sql_cmd);
    cout << "[AllTaskRecordData] json_data size: " << json_data.size() << endl;
    for(int i=0; i< json_data.size(); i++){
        Json::Value record_item = json_data[i];
        if(i==0) 
            cout << "record_item: " << record_item << endl;
        TaskRecord task_record;
        TaskGroup task_group;

        TaskSingle task_single;
        string map_name;
        if(file_manager::CheckItemIsValid(record_item, "map_name")){
            map_name = record_item["map_name"].asString();
            task_single.task_base.map_base.name = map_name;
            task_group.task_list.emplace_back(task_single);
        }

        TaskPicture task_picture;
        if(file_manager::CheckItemIsValid(record_item, "clean_map_url")){
            task_picture.map_name = map_name;
            task_picture.png_file_path = record_item["clean_map_url"].asString();
            task_record.task_pictures.emplace_back(task_picture);
        }
            
        if(file_manager::CheckItemIsValid(record_item, "task_name"))
            task_group.group_name = record_item["task_name"].asString();
        if(task_group.group_name == "trans_floor" || 
            task_group.group_name == "charging"  || 
            task_group.group_name == "p2p_move") continue;

        if(file_manager::CheckItemIsValid(record_item, "task_id"))
            task_group.group_id = record_item["task_id"].asString();

        if(file_manager::CheckItemIsValid(record_item, "group_name"))
            task_group.timertask_name = record_item["group_name"].asString();
        // task_group.timertask_id = "";

        if(file_manager::CheckItemIsValid(record_item, "add_time"))
            task_record.add_time = record_item["add_time"].asString();

        if(file_manager::CheckItemIsValid(record_item, "start_time"))
            task_record.start_time = record_item["start_time"].asString();

        if(file_manager::CheckItemIsValid(record_item, "end_time"))
            task_record.end_time = record_item["end_time"].asString();
        
        if(file_manager::CheckItemIsValid(record_item, "cov_rate")){
            string str = record_item["cov_rate"].asString();
            if(!str.empty()){
                task_record.coverage_rate = stof(str);
            }
        }

        if(file_manager::CheckItemIsValid(record_item, "theoretic_cov_rate")){
            string str = record_item["theoretic_cov_rate"].asString();
            if(!str.empty()){
                task_record.total_area = stof(str);
            }
        }

        if(file_manager::CheckItemIsValid(record_item, "actual_working_duration")){
            string str = record_item["actual_working_duration"].asString();
            if(!str.empty()){
                task_record.working_time = stof(str);
            }
        }
            
        task_record.cleaned_area = task_record.total_area * task_record.coverage_rate;
        task_record.uncleaned_area = task_record.total_area - task_record.cleaned_area;

        task_record.is_assigned = true;
        task_record.status = TaskState::FINISHED;
        if(record_item.isMember("is_cancel")){
            string is_cancel_str = record_item["is_cancel"].asString();
            if(is_cancel_str == string("1")){
                task_record.status = TaskState::USER_CANCEL;
                if(task_record.coverage_rate < 0.1){
                    task_record.is_assigned = false;
                }
            }
        }

        if(file_manager::CheckItemIsValid(record_item, "status_code")){
            string str = record_item["status_code"].asString();
            if(!str.empty()){
                task_record.error_code.error_code = stoi(str);
            }
        }

        if(file_manager::CheckItemIsValid(record_item, "status_msg")){
            task_record.error_code.error_msg = record_item["status_msg"].asString();
        }

        // cout << "i: " << i << ", group_name=" + task_record.task_group.group_name
        //     << ", group_id=" + task_record.task_group.group_id 
        //     << endl;
        task_record.task_group = task_group;
        task_record_list.emplace_back(task_record);
    }
    return task_record_list;
}



